Skip to content

fix: restore saved credentials when switching back to original auth mode#7911

Open
pooja-bruno wants to merge 5 commits into
usebruno:mainfrom
pooja-bruno:fix/auth-mode-switch-preserves-saved
Open

fix: restore saved credentials when switching back to original auth mode#7911
pooja-bruno wants to merge 5 commits into
usebruno:mainfrom
pooja-bruno:fix/auth-mode-switch-preserves-saved

Conversation

@pooja-bruno
Copy link
Copy Markdown
Collaborator

@pooja-bruno pooja-bruno commented May 5, 2026

Description

JIRA

Fixes #5636

Contribution Checklist:

  • I've used AI significantly to create this pull request
  • The pull request only addresses one issue or adds one feature.
  • The pull request does not introduce any breaking changes
  • I have added screenshots or gifs to help explain the change if applicable.
  • I have read the contribution guidelines.
  • Create an issue and link to the pull request.

Note: Keeping the PR small and focused helps make it easier to review and merge. If you have multiple changes you want to make, please consider submitting them as separate pull requests.

Publishing to New Package Managers

Please see here for more information.

Summary by CodeRabbit

  • Bug Fixes

    • Restored saved authentication data when switching back to a previously configured auth mode so credentials (e.g., tokens) and draft state are preserved.
  • Tests

    • Added end-to-end tests covering auth-mode switching across request/collection/folder scopes and the draft-change indicator to prevent regressions.
  • New Features

    • Test helpers for selecting auth modes, reading/typing single-line auth fields, and creating collections with a chosen file format.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 5, 2026

Walkthrough

Reducers now preserve a saved auth object into the draft when switching back to its mode; otherwise the draft is reset to { mode }. Adds Playwright helpers and E2E tests that validate draft indicator and credential restoration across request, collection, and folder scopes for bru/yml formats.

Changes

Auth Mode Switching Preserves Saved Credentials

Layer / File(s) Summary
Auth Mode Reducers
packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js
updateRequestAuthMode, updateCollectionAuthMode, and updateFolderAuthMode compare the selected mode to the saved mode and deep-clone the saved *.request.auth into the corresponding *.draft.*.request.auth when they match; otherwise they set the draft to { mode: newMode }.
Test Helper Infrastructure
tests/utils/page/actions.ts
createCollection gains optional `format?: 'bru'
E2E Test: Auth Mode Switch (Draft Indicator)
tests/auth/auth-mode-switch-draft-indicator.spec.ts
Parameterized scenario for bru and yml formats asserting draft indicator visibility and token restoration when saving, switching away unsaved, and returning to a saved Bearer token.
E2E Test: Auth Mode Switch (Credential Preservation)
tests/auth/auth-mode-switch.spec.ts
Three tests covering Request-, Collection-, and Folder-level auth: save a Bearer token, switch to other modes and assert empty unrelated fields, then return to Bearer and assert saved token is restored.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • helloanoop
  • lohit-bruno
  • naman-bruno
  • bijin-bruno

Poem

🔐 When modes are flipped and doubts ensue,
Redux remembers the token for you.
Switch away, then back, and fields reappear—
Saved creds return, the state is clear. ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Title clearly summarizes the main fix: restoring saved credentials when switching back to the original auth mode, which matches the core changeset objective.
Linked Issues check ✅ Passed The PR implementation preserves saved auth configuration when switching modes and restores it when returning to the original mode, directly addressing issue #5636's requirement to retain filled authorization values across mode switches.
Out of Scope Changes check ✅ Passed All changes are directly aligned with the stated objective: reducer updates for auth preservation, E2E tests validating the draft indicator behavior, integration tests confirming saved credentials restoration, and test utilities supporting the new functionality.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
tests/request/auth-mode-switch.spec.ts (3)

33-37: ⚖️ Poor tradeoff

readField is coupled to the CodeMirror v5 DOM API — worth a data-testid fallback.

return editor.evaluate((el: any) => (el as any).CodeMirror?.getValue() ?? '');

el.CodeMirror is a CM5-specific instance property. If Bruno ever upgrades to CodeMirror 6 (which attaches its state differently), this evaluates to '' for every assertion, silently turning all readField assertions into vacuous passes. Wiring a data-testid attribute to the underlying <textarea> that CM5 maintains in sync, or an aria-label, would make readField CM-version-agnostic.

As per coding guidelines: "Add data-testid to testable elements for Playwright."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/request/auth-mode-switch.spec.ts` around lines 33 - 37, readField
currently relies solely on the CodeMirror v5 DOM API (reading
el.CodeMirror.getValue()), which will silently break if the editor is upgraded;
update readField to first try the existing CodeMirror path and then fall back to
reading the underlying <textarea> value via a test id or accessible label (e.g.
query for textarea[data-testid="${labelText}"] or
textarea[aria-label="${labelText}"] and return its .value) so assertions remain
valid across CM versions; also ensure the component under test includes a stable
data-testid on the editor textarea so fieldEditor/readField can locate it.

84-124: ⚡ Quick win

Collection and Folder tests only cover the happy path — consider adding parity steps with the Request test.

The Request test (lines 44–82) includes 5 well-structured steps:

  1. Save Bearer credentials
  2. Bearer → Basic → Bearer restores token ✓ (the main fix)
  3. Switching to a non-saved mode shows empty fields
  4. Switching to a third unrelated mode also leaves fields empty
  5. Multiple round-trips to the saved mode still restore correctly

The Collection (lines 84–101) and Folder (lines 104–124) tests only cover step 2. If a bug were introduced that only affects Collection- or Folder-level auth mode switching (e.g., the updateCollectionAuth / updateFolderAuth reducers that clear auth), steps 3–5 would silently pass in the Collection/Folder paths. Adding at least step 3 (non-saved mode shows empty fields) would give meaningful regression coverage for the collection/folder reducers independently.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/request/auth-mode-switch.spec.ts` around lines 84 - 124, Add the
missing parity check that switching to a non-saved auth mode clears fields:
after the "Save Bearer" step in both the Collection and Folder tests (identify
blocks that call createCollection/createFolder, selectAuthMode, typeIntoField,
and click Save) add a step that selects a different mode that was never saved
(e.g., selectAuthMode(page, 'API Key') or 'Basic Auth' as appropriate) and
assert using readField(...) that the relevant fields are empty; then switch back
to 'Bearer Token' and assert the saved token is restored with expect.poll(() =>
readField(page, 'Token')).toBe('collection-bearer-token' /
'folder-bearer-token') to mirror the Request test's non-saved-mode coverage.

16-21: 💤 Low value

Static analysis flag on new RegExp(...) is a false positive here.

labelText is always passed as a static string literal ('Token', 'Username', 'Password') with no regex metacharacters, so the ReDoS warning is inapplicable. The exact-boundary regex (^...$) is the right approach to avoid partial-text false matches on labels like "Token" vs "Bearer Token."

If you want to silence the linter cleanly:

✨ Suggested fix
-    .filter({ hasText: new RegExp(`^${labelText}$`) })
+    .filter({ hasText: labelText, exact: true })

Playwright's filter({ hasText: ..., exact: true }) does case-sensitive exact string matching, removing the regex entirely.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/request/auth-mode-switch.spec.ts` around lines 16 - 21, The linter
flags the use of new RegExp in the fieldEditor helper; replace the regex-based
match with Playwright's exact string match to silence the false positive and
keep exact-boundary behavior: update the fieldEditor function (named
fieldEditor) to use filter({ hasText: labelText, exact: true }) instead of
filter({ hasText: new RegExp(`^${labelText}$`) }) so it performs case-sensitive
exact matching for labels like "Token" vs "Bearer Token".
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@tests/request/auth-mode-switch.spec.ts`:
- Around line 33-37: readField currently relies solely on the CodeMirror v5 DOM
API (reading el.CodeMirror.getValue()), which will silently break if the editor
is upgraded; update readField to first try the existing CodeMirror path and then
fall back to reading the underlying <textarea> value via a test id or accessible
label (e.g. query for textarea[data-testid="${labelText}"] or
textarea[aria-label="${labelText}"] and return its .value) so assertions remain
valid across CM versions; also ensure the component under test includes a stable
data-testid on the editor textarea so fieldEditor/readField can locate it.
- Around line 84-124: Add the missing parity check that switching to a non-saved
auth mode clears fields: after the "Save Bearer" step in both the Collection and
Folder tests (identify blocks that call createCollection/createFolder,
selectAuthMode, typeIntoField, and click Save) add a step that selects a
different mode that was never saved (e.g., selectAuthMode(page, 'API Key') or
'Basic Auth' as appropriate) and assert using readField(...) that the relevant
fields are empty; then switch back to 'Bearer Token' and assert the saved token
is restored with expect.poll(() => readField(page,
'Token')).toBe('collection-bearer-token' / 'folder-bearer-token') to mirror the
Request test's non-saved-mode coverage.
- Around line 16-21: The linter flags the use of new RegExp in the fieldEditor
helper; replace the regex-based match with Playwright's exact string match to
silence the false positive and keep exact-boundary behavior: update the
fieldEditor function (named fieldEditor) to use filter({ hasText: labelText,
exact: true }) instead of filter({ hasText: new RegExp(`^${labelText}$`) }) so
it performs case-sensitive exact matching for labels like "Token" vs "Bearer
Token".

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 29932aca-edfd-42f5-868b-6a6d426a9699

📥 Commits

Reviewing files that changed from the base of the PR and between d332d8e and fe37f54.

📒 Files selected for processing (2)
  • packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js
  • tests/request/auth-mode-switch.spec.ts

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
tests/utils/page/actions.ts (1)

1248-1252: 💤 Low value

Consider removing .first() if only one editor is expected.

The readField helper uses .first() at line 1249, which suggests multiple editors might match the selector. If only one editor per label is expected in the auth forms, calling .first() might mask issues if the selector accidentally matches multiple elements. However, if this is defensive coding for edge cases, it's acceptable.

♻️ Alternative: drop `.first()` if ambiguity isn't expected
-const readField = async (page: Page, labelText: string): Promise<string> => {
-  const editor = fieldEditor(page, labelText).first();
-  await editor.waitFor({ state: 'visible' });
-  return editor.evaluate((el: any) => (el as any).CodeMirror?.getValue() ?? '');
-};
+const readField = async (page: Page, labelText: string): Promise<string> => {
+  const editor = fieldEditor(page, labelText);
+  await editor.waitFor({ state: 'visible' });
+  return editor.evaluate((el: any) => (el as any).CodeMirror?.getValue() ?? '');
+};
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/utils/page/actions.ts` around lines 1248 - 1252, The helper readField
currently calls .first() on the locator returned by fieldEditor(page,
labelText), which can hide selector collisions; remove the .first() call so
readField uses the locator returned by fieldEditor(page, labelText) directly,
update the subsequent awaits/evaluate to operate on that locator (i.e., await
fieldEditor(page, labelText).waitFor(...) and then evaluate on the same
locator), and optionally add an explicit uniqueness assertion (e.g., check
locator.count() === 1 or use an expect-to-have-count assertion) if you want to
fail fast when multiple editors are matched.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@tests/utils/page/actions.ts`:
- Around line 1248-1252: The helper readField currently calls .first() on the
locator returned by fieldEditor(page, labelText), which can hide selector
collisions; remove the .first() call so readField uses the locator returned by
fieldEditor(page, labelText) directly, update the subsequent awaits/evaluate to
operate on that locator (i.e., await fieldEditor(page, labelText).waitFor(...)
and then evaluate on the same locator), and optionally add an explicit
uniqueness assertion (e.g., check locator.count() === 1 or use an
expect-to-have-count assertion) if you want to fail fast when multiple editors
are matched.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 11bc296d-fcd9-49e6-a5db-32c3ac4aa9ca

📥 Commits

Reviewing files that changed from the base of the PR and between fe37f54 and e1c34b2.

📒 Files selected for processing (4)
  • packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js
  • tests/auth/auth-mode-switch-draft-indicator.spec.ts
  • tests/auth/auth-mode-switch.spec.ts
  • tests/utils/page/actions.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js

sid-bruno
sid-bruno previously approved these changes May 14, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/utils/page/actions.ts`:
- Around line 1255-1260: The RegExp built in the fieldEditor helper uses
unescaped labelText which allows regex metacharacters to break matching; update
fieldEditor to escape labelText (reuse the existing escapeRegExp helper used
elsewhere) before constructing new RegExp so label strings like "Client ID
(Prod)" match literally; specifically, call escapeRegExp(labelText) when
creating the RegExp inside the fieldEditor function.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 60cf4e56-fef4-4775-ba30-51a24f0c9db6

📥 Commits

Reviewing files that changed from the base of the PR and between e1c34b2 and 43948b4.

📒 Files selected for processing (2)
  • packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js
  • tests/utils/page/actions.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js

Comment thread tests/utils/page/actions.ts
sid-bruno
sid-bruno previously approved these changes May 14, 2026
sid-bruno
sid-bruno previously approved these changes May 14, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/utils/page/actions.ts`:
- Around line 1267-1270: The selectAuthMode helper is flaky because it clicks
without waiting for visibility and uses a loose hasText match; update
selectAuthMode to await visibility on the trigger (the locator
'.auth-mode-label'), click it, then locate the option using an exact-text
locator (reference: selectAuthMode, '.auth-mode-label', '.dropdown-item') such
as getByText/getByRole or locator with exact text matching, wait for that option
to be visible/attached, and then click it—this ensures deterministic selection
and avoids mis-targeted clicks.
- Around line 1278-1281: The helper typeIntoField currently clicks and appends
text which makes input nondeterministic; change it to clear the field before
entering new text by using the Playwright fill API or by selecting-all then
deleting: replace the click+keyboard.type logic in typeIntoField with a call to
fieldEditor(page, labelText).fill(value) (or, if fieldEditor returns an
ElementHandle, focus it then send a select-all+delete before typing), so the
field is emptied then set deterministically to value.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 84d8e3bc-269d-4499-ac95-64a62573913a

📥 Commits

Reviewing files that changed from the base of the PR and between 43948b4 and 7e13b87.

📒 Files selected for processing (1)
  • tests/utils/page/actions.ts

Comment thread tests/utils/page/actions.ts
Comment thread tests/utils/page/actions.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Switching between Authorizations should keep my filled values when switching back

2 participants